import 'dart:math';

import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);
  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  var _color = Colors.red;
  var _slot = 0;
  late double _stackTop;
  late List _colors = [];
  final _stackGlobalKey = GlobalKey();

  _shuffle() {
    _color = Colors.primaries[Random().nextInt(Colors.primaries.length)];
    _colors = List.generate(8, (index) => _color[(index + 1) * 100]);

    setState(() => _colors.shuffle());
  }

  _checkWinCondition() {
    List lum = _colors.map((i) => i.computeLuminance()).toList();

    bool success = true;
    for (int i = 0; i < lum.length - 1; i++) {
      if (lum[i] > lum[i + 1]) {
        success = false;
        break;
      }
    }
    success ? print('You win!') : null;
  }

  _pointerMove(details) {
    if (_slot == _colors.length - 1) return;
    if (_slot == 0) return;

    final y = details.position.dy - _stackTop;
    final t = _colors[_slot];

    setState(() {
      if (y > (_slot + 1) * Box.height) {
        _colors[_slot] = _colors[_slot + 1];
        _colors[_slot + 1] = t;
        _slot++;
      }

      if (y < _slot * Box.height) {
        _colors[_slot] = _colors[_slot - 1];
        _colors[_slot - 1] = t;
        _slot--;
      }
    });
  }

  _onBoxDrag(color) {
    _slot = _colors.indexOf(color);
    final renderBox =
        _stackGlobalKey.currentContext!.findRenderObject()! as RenderBox;
    _stackTop = renderBox.localToGlobal(Offset.zero).dy;
  }

  @override
  initState() {
    super.initState();
    _shuffle();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text(widget.title)),
      body: Center(
        child: Column(
          children: [
            const SizedBox(height: 32),
            const Text("Welcome", style: TextStyle(fontSize: 32)),
            const SizedBox(height: 32),
            Container(
              width: Box.width - Box.margin * 2,
              height: Box.height - Box.margin * 2,
              decoration: BoxDecoration(
                color: _color[900],
                borderRadius: BorderRadius.circular(10.0),
              ),
              child: const Icon(Icons.lock, color: Colors.white),
            ),
            const SizedBox(height: Box.margin * 2),
            Expanded(
              child: Listener(
                onPointerMove: _pointerMove,
                child: SizedBox(
                  width: Box.width,
                  child: Stack(
                    key: _stackGlobalKey,
                    children: List.generate(_colors.length, (index) {
                      return Box(
                        color: _colors[index]!,
                        y: index * Box.height,
                        onDrag: _onBoxDrag,
                        onEnd: _checkWinCondition,
                        key: ValueKey(_colors[index]),
                      );
                    }),
                  ),
                ),
              ),
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _shuffle,
        child: const Icon(Icons.refresh),
      ),
    );
  }
}

class Box extends StatelessWidget {
  static const width = 250.0;
  static const height = 50.0;
  static const margin = 2.0;

  final double y;
  final Color color;
  final Function(Color) onDrag;
  final Function() onEnd;

  const Box({
    required this.color,
    required this.y,
    required this.onDrag,
    required this.onEnd,
    required Key key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final _container = Container(
      width: width - margin * 2,
      height: height - margin * 2,
      decoration: BoxDecoration(
          color: color, borderRadius: BorderRadius.circular(10.0)),
    );

    return AnimatedPositioned(
      duration: const Duration(milliseconds: 500),
      top: y,
      child: Draggable(
        onDragStarted: () => onDrag(color),
        onDragEnd: (_) => onEnd(),
        feedback: _container,
        child: _container,
        childWhenDragging: Visibility(visible: false, child: _container),
      ),
    );
  }
}
